-
Notifications
You must be signed in to change notification settings - Fork 450
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support an 'owner' key in region_highlight. #57
Support an 'owner' key in region_highlight. #57
Conversation
This is to allow plugins to easily remove only entries they had added. See zsh-users/zsh-syntax-highlighting#418 and the cross-referenced issues.
Doc/Zsh/zle.yo
Outdated
enditemize() | ||
|
||
For example, | ||
|
||
example(region_highlight=("P0 20 bold")) | ||
example(region_highlight=("P0 20 bold owner=myplugin")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Older zsh's parse this as equivalent to P0 20 none
unless a comma is added after bold
. Is there a better option?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hold on, doesn't using a comma separator give us backward compatibility?
region_highlight=("P0 20 bold,owner=myplugin")
seems to work in current zsh.
We may lose the owner in an old zsh but that only loses us the ability to prevent plugins from interfering with each other. Losing the bold is a backward compatibility problem.
It could be worth thinking about other uses for the owner field. We could add a region_precedence array which might contain, e.g. ( vi-exchange builtin z-s-h ) so z-s-h doesn't need to duplicate the code for rendering the region/selection.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the review.
I considered using a comma separator, but (1) the owner's identity seemed like metadata, not an intrinsic part of the typographic specification; and (2) the syntax in the PR was mildly easier to implement.
I'll sleep on a numeric precedence=
key (à la add-zle-hook-widget style values) and solving the region/standout duplication issue and get back to you on them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough. Do I understand correctly that the only downside of your approach (with a space) is that for backwards compatibility, you need a trailing comma on the attributes if there isn't one, e.g. bold,
I agree that it logically belongs separately so is cleaner.
Any precedence feature is a separate matter really. It just came to mind when looking at this. Rather than a numeric precedence=
key, I was just thinking of an array listing owners in order. By default it'd just contain an entry for the builtin stuff. Plugins would probably add themself to either the beginning or end and users could always reorder them. There are probably other schemes that could work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand correctly that the only downside of your approach (with a space) is that for backwards compatibility, you need a trailing comma on the attributes if there isn't one, e.g.
bold,
It's the only downside I'm aware of, yes. But there's a reason I've posted this for review :)
Any precedence feature is a separate matter really. It just came to mind when looking at this. Rather than a numeric
precedence=
key, I was just thinking of an array listing owners in order. By default it'd just contain an entry for the builtin stuff. Plugins would probably add themself to either the beginning or end and users could always reorder them. There are probably other schemes that could work.
The idea being that plugin authors are better placed than users to determine the best relative order of highlights, I guess? For example, if zsh-autosuggestions were to highlight a suggestion that had just been inserted, that would probably want to apply after z-sy-h's highlights?
Compare the proof-of-concept docs patch I posted in zsh-users/zsh-autosuggestions#529 (comment) under the heading "Describe alternatives you've considered". (None of the dicsussion in the issue is about that diff, though the LASTWIDGET issue in Eric's latest comment may be of independent interest.)
Src/Zle/zle_refresh.c
Outdated
strp++; | ||
|
||
if (strpfx("owner=", strp)) | ||
rhp->owner = ztrdup(strp + 6); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given the above comment, this shouldn't copy the entire rest of the string, but only up to the next space, for extensibility (forward compatibility).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be resolved by the just-pushed commits. (The hex commit id's will be changed later when I squash them, so I'm not pointing to a specific commit.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New tests added for this.
Just brainstorming a bit. As a plugin author, setting an "owner" value is a bit more broad of a use case than I need. All I really need is to be able to uniquely identify certain highlights that I created so that I can delete them later on. If when I create a new highlight, I could get back an automatically generated unique identifier for that highlight in REPLY, that would be enough for me. @danielshahaf what would you think of adding a new flag (maybe
I'm thinking that highlights added this way would not be accessible through the |
Thanks for the review.
Could you elaborate on why z-asug needs unique identifiers? I take it z-asug's use-case wouldn't be addressed by a hardcoding a fixed string or three, but why? In terms of the PR as it stands, the closest equivalent to your functionality would be something along the lines of: owner="z-asug:$RANDOM:"
region_highlight+=( "P0 20 bold owner=$owner" ) and afterwards remove it using the method described in the docs change in this PR. (Aside: I'll change "owner" in the PR to some more generic term before posting/merging this.)
On the one hand, encapsulating the details is appealing. I suspect, however, that a blackbox that only supports "add a highlight" and "delete a highlight given its nonce" would be a bit too specialized. On the other hand, the approach I described above seems to me to be more closely aligned with PEP 20's principles and to be more generic/flexible. Indeed, it would be easy to implement your proposed API around the API in the PR: zle-h() {
if [[ $1 == -d ]]; then
region_highlight=( ${region_highlight:#*owner="$2"} )
else
setopt localoptions nowarncreateglobal
REPLY="$RANDOM.$RANDOM"
region_highlight+=( "$1 owner=$REPLY" )
fi
} … whereas the converse would require callers to maintain their own records of which nonces (returned values of $REPLY) identify which highlights. For example, z-sy-h would have to maintain a simple array of all nonces it has set, and then delete all of them (perhaps using a Not sure which I prefer, yet. |
The need for unique identifiers is just so that I can be sure that I’m not removing anything else when I delete my highlight. If it weren’t unique, there may be a chance that I remove something else unintentionally. Hard coding a fixed string would work practically but my point was that it’s not functionality that I need. I don’t care what the identifier value is, so having to specify some value for it is just extra work for me to do. It would be nice if zsh could handle it for me. It’s not a big deal, just a thought while we’re coming up with new functionality 😄
As I think about this more I’m wondering if would be feasible to just store the highlights added via the new zle flag to region_highlight. The unique identifier would then be just an optional attribute of a highlight- present for those added via zle and not present for those added through setting the param. |
> Could you elaborate on why z-asug needs unique identifiers? I take it z-asug's use-case wouldn't be addressed by a hardcoding a fixed string or three, but why?
The need for unique identifiers is just so that I can be sure that I’m
not removing anything else when I delete my highlight. If it weren’t
unique, there may be a chance that I remove something else
unintentionally. Hard coding a fixed string would work practically but
my point was that it’s not functionality that I need. I don’t care what
the identifier value is, so having to specify some value for it is just
extra work for me to do. It would be nice if zsh could handle it for
me. It’s not a big deal, just a thought while we’re coming up with new
functionality 😄
WDYT of, say, «region_highlight+=( "P0 20 bold autoremove=yes" )» to add
an entry that would be automatically removed (by add-zle-hook-widget or
possibly zle itself) at some appropriate time? (What would an
appropriate time be in your use-case?)
I'll sleep on the rest of your comment and reply further later.
|
Okay, so you're proposing to encapsulate adding a single entry and removing a single entry. However, operations such as "remove all my entries", "remove all entries", "enumerate entries", etc., would not be encapsulated, so they'd only be possible to implement by directly accessing the array. Doesn't that somewhat negate the benefits of encapsulation, at least at the |
Hmm yeah this could probably work. The appropriate time for z-asug could probably be any time between the end of a redraw and the start of the next redraw cycle (just before the line-pre-redraw hooks are called). This would probably be the right time for z-sy-h as well. So setting that flag would be kind of like saying "I want this highlight to be around for the next redraw cycle, but remove it after that". I'm a little apprehensive to give up control of when exactly the entries are removed, but I'm struggling to come up with any real justification for that apprehension. Would there be cases where someone would want a highlight to stick around until they manually remove it?
That's basically what I'm thinking. You could still support "remove all my entries" by passing multiple tokens to
Somewhat yeah. The benefit we'd get from adding
I think the implementation could technically change as long as the API contracts are kept intact. The API contracts being the details of both |
Yes.
Who's "someone"? A user? A plugin author? Whoever it is, couldn't they add their entry without If you're getting at making
There is: by convention,
It's certainly possible to encapsulate these other operations as well.
Do you see any other use-cases besides setting $REPLY as mentioned?
So, the code you're proposing is: local s="P0 20 bold"
zle -h -- $s
typeset -g _z_asug_cookie=$REPLY and the code I'm proposing is: local s="P0 20 bold"
typeset -g _z_asug_cookie=:z-asug:$RANDOM:
region_highlight+=( "$s owner=$_z_asug_cookie" ) And the main difference is that your proposal involves designing, implementing, and documenting a new API. If the old API remains fully supported, the first proposal would increase zle's maintenance burden; and if we don't, the existing UI would have to be deprecated [which has a cost in man-hours too], and subsequently plugin maintainers would have to update their code. I am sorry, but I do not consider separating the generation-of-nonces concern from z-asug to be sufficient justification for imposing these costs on zle and other plugins. What's so foreboding about the second alternative? All you said was:
I see that that the second alternative's design is not in the first normal form, and that it allows stuff like random write access ( If it helps, we could add some sort of magic parameter that expands to a different value every time it's referenced: perhaps $AUTOINCREMENT (expands to 0, then 1, then 2, then 3, …) or $NONCE (value only guaranteed to be unique; maybe $UUIDGEN after Or you could propose that the
Well, yes, that is an example of encapsulating an implementation detail. What I fail to see is why that detail needs to be encapsulated in the first place. Do you expect best practices in the area of nonce-generation to change in the coming years? Next steps:
Cheers! |
"id" perhaps. Is nice and short. Could document a convention of prefixing it with a string to identify the owning plugin. |
Most definitely yes. Most of my uses of region_highlight fall into this category. The vi-exchange plugin of mine that is public needs the highlight to stay around. An autoremove, entry seems reasonable. (the shorter name might be nice). Could be good to have the value make it clear what the remove criteria would be - also useful for future extensions, e.g. |
I can't say I really like the If it generates an id for you in |
What "shorter name" are you referring to? None has been proposed.
+1 |
I was thinking of |
That was a typo or similar. I meant a not the. Ideas that come to mind include, "expire", "expiry", "lifetime", "remove", "scope", "transient", "tmp" |
I'm not especially fond of such identifying initialisms. It's only used within |
In my experience, self-descriptive names are useful. See, for example, https://subversion.apache.org/issue3744. That's why I'm not that fond of bare But I get that Do we need the Are there any outstanding concerns with the functionality, other than the names of the API entry points? |
With the scope limited to the region_highlight array, I can't see there being any confusion.
"stroke" is too suggestive of a movement in it's meaning which I don't think applies here. It may have subtle US/UK differences in meaning. How about "mark". A thesaurus also turns up "tag", "stamp", "label" and "badge". In a somewhat different vein, "memo" or "key".
Checking back over the discussion, I don't think you exactly fleshed out when auto-removal would occur. It perhaps removes the need from z-s-h and any widget that re-applies things any time the buffer changes. But for longer persisting things like vi-exchange, it'd still be useful. |
> In my experience, self-descriptive names are useful. See, for example, https://subversion.apache.org/issue3744. That's why I'm not that fond of bare `id`.
With the scope limited to the region_highlight array, I can't see there being any confusion.
Yeah, but a unique name would be more greppable. `grep -R rhid` would in practice have near-100% specificity and sensitivity; that's not the case for either `grep -Rw id` or `grep -R 'region_highlight.*id'`. [This goes not only for `rhid` but also for any other sufficiently-unique term.]
> But I get that `rhid` is a bit cryptic. Kinda comes with the territory of being short, though. Anyway, how about, say, `stroke` or `stroke_id`?
"stroke" is too suggestive of a movement in it's meaning which I don't think applies here. It may have subtle US/UK differences in meaning. How about "mark". A thesaurus also turns up "tag", "stamp", "label" and "badge". In a somewhat different vein, "memo" or "key".
I was thinking of the noun sense of 'stroke', but yeah, something else. 'label' and 'memo' both sound good.
> Do we need the `owner=` functionality at all if we have the `autoremove` (or `expiry`) functionality?
Checking back over the discussion, I don't think you exactly fleshed out when auto-removal would occur.
Autoremoval should take place at the start of the following redraw cycle (the cycle _after_ the one zle-line-pre-redraw is running as part of), I suppose?
It perhaps removes the need from z-s-h and any widget that re-applies things any time the buffer changes. But for longer persisting things like vi-exchange, it'd still be useful.
Ack usefulness. So, I think the subtotal up to this point is to add both memo= (née owner=) and expiry=next-redraw (née autoremove=yes)? If so, let's take this proposal to -workers@.
|
No, was just wondering if we would still need the "owner" solution. Sounds like we do.
No that's the only one I'm seeing for now.
Makes sense. I figured this would be the outcome but thought I'd give my 2 cents anyway.
This is an interesting idea. Probably not necessary for now, but I'll keep it in mind for the future.
Nothing in particular. I was just thinking it might be a nice feature to implement so that clients (plugins, users, etc.) wouldn't need to worry about implementing the nonce-generation themselves.
Do we need both? I would be fine with just memo/owner for now. |
> I think the subtotal up to this point is to add both memo= (née owner=) and expiry=next-redraw (née autoremove=yes)?
Do we need both? I would be fine with just memo/owner for now.
Good point. Yes, let's add just memo=, then. Unless implementing expiration in zle itself would be a noticeable performance gain? (@psprint?)
|
Thread: workers/46001 |
[s/owner=/memo=/g] Support a 'memo' key in region_highlight. This is to allow plugins to easily remove only entries they had added. See zsh-users/zsh-syntax-highlighting#418 and the cross-referenced issues. This was initially worked on at zsh-users#57, where it was initially called "owner=".
[Remove a magic number]
Incomplete; see test. Fixed in the next commit.
Pushed some commits that rename |
Two TODO comments remain: + /* ### TODO: Consider optimizing the common case that memo_start to
+ * end-of-string is entirely ASCII */
+ while (1) { + /* TODO: save rhp->memo here? */
if (zlemetaline) {
newrhp->start = rhp->start_meta; |
} else | ||
i += nbytes; | ||
} | ||
rhp->memo = ztrduppfx(memo_start, memo_end - memo_start); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where's the corresponding free()?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pushed.
This causes memos to be preserved across invocations of _cmdstring, at least (probably because _cmdstring calls `compset -q` and set_comp_sep() calls zle_save_positions()).
The allocation in zle_set_highlight() did not require an update.
39d4460
to
adf432e
Compare
Posted this PR as of 23d1edc, squashed, to -workers@ in workers/46068. |
Merged in dd6e702. Thanks for all the reviews and testing! I'll go back to zsh-users/zsh-syntax-highlighting#418 and see what can be done to move it forward, now. |
…o= support. This is useful when multiple plugins add region_highlight entries and subsequently want to remove only their own entries. Without this functionality, recognizing one's region_highlight entries is not trivial because the 'start' and 'end' offsets are modified by editing of $BUFFER and the highlight specification may not be unique or distinctive. The tweaks are as follows: - Change zfree() to zsfree() per workers/46070. - Remove the mem.c hunk, as it changed the signature of only one out of two alternative definitions of zsfree(). (The definition that hunk touched is the one that's not used by default.)
This is to allow plugins to easily remove only entries they had added. See zsh-users/zsh-syntax-highlighting#418 and the cross-referenced issues.